﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using System.Web.UI;
using MvcEngine.Mvc.Models.ViewModels;
using MvcEngine.Core.Utils;
using MvcEngine.Core;

using MvcEngine.Core.Repositories;
using MvcEngine.Core.Helpers;
using MvcEngine.Mvc.Extensions;
using MvcEngine.Core.Validation;
using System.Text.RegularExpressions;
using MvcEngine.Mvc.Models;
using MvcEngine.Core.Exceptions;
using MvcEngine.Core.Services;
using MvcEngine.Core.Localization;
using MvcEngine.Mvc.Filters;
using MvcEngine.Core.Account;
using MvcEngine.Mvc.Controllers;
using MvcEngine.Core.Pagination;
using MvcEngine.Core.Base;

namespace MvcEngine.Mvc.BackOffice.Controllers
{
    public class UserController : BaseController
    {
        #region Private Fields

        private IUserRepository userRepository = null;

        #endregion

        #region Constructors

        public UserController(IUserRepository userRepository)
        {
            this.userRepository = userRepository;
        }

        #endregion

        #region Public methods (User)

        public MvcEngineModel List(int? pageNumber)
        {
            if (!pageNumber.HasValue)
                pageNumber = 1;
            if (pageNumber.Value <= 0)
                return new MvcEngineModel { ViewName = "InvalidPageRequest" };

            LoadOptions options = IoC.Resolve<LoadOptions>();
            options.PageNumber = pageNumber.Value;
            options.PageSize = 10;
            IPagination<User> pagination = AccountManager.Current.GetUsers(options);
            if (pagination.TotalItems == 0)
                return new MvcEngineModel { ViewName = "Empty" };
            if (pageNumber.Value > pagination.TotalPages)
                return new MvcEngineModel { ViewName = "InvalidPageRequest" };
            return new MvcEngineModelItem<IPagination<User>> { Item = pagination, ViewName = "List" };
        }

        public MvcEngineModel Edit(Guid id)
        {
            return new MvcEngineModelItem<User>()
            {
                Item = AccountManager.Current.GetUser(id)
            };
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Delete(Guid id)
        {
            return Redirect(Url.Users());
        }

        #endregion

        #region Public methods (Admin)

        [AcceptVerbs(HttpVerbs.Get)]
        public virtual MvcEngineModel LogOn()
        {
            return new MvcEngineModel();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public virtual object LogOn(string userName, string password, bool rememberMe, string returnUrl)
        {
            if (!ValidateLogOn(userName, password))
            {
                return LogOn();
            }

            FormsAuthenticationHelper.Current.SignIn(userName, rememberMe);
            if (!String.IsNullOrEmpty(returnUrl))
            {
                if (Uri.IsWellFormedUriString(returnUrl, UriKind.Relative))
                    return Redirect(returnUrl);
            }
            return Redirect(Url.BackOffice());
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public virtual ActionResult LogOff()
        {
            FormsAuthenticationHelper.Current.SignOut();
            return Redirect(Url.BackOffice());
        }

        //[AcceptVerbs(HttpVerbs.Get)]
        //public void Language(string language)
        //{
        //    if (string.IsNullOrEmpty(language))
        //    {
        //        LogHelper.Current.WriteError("Language can't be null or empty.");
        //        Response.Redirect(Request.UrlReferrer.ToString());
        //    }

        //    CultureInfo culture = null;
        //    try
        //    {
        //        culture = new CultureInfo(language);
        //    }
        //    catch (ArgumentException)
        //    {
        //        culture = new CultureInfo(SiteContext.Current.Site.Culture);
        //    }

        //    Response.Cookies.Add(new HttpCookie(Constants.UserSettings.SelectedCulture, language));
        //    Response.Redirect(Request.UrlReferrer.ToString());
        //}

        #endregion

        #region Protected methods

        protected virtual bool ValidateLogOn(string email, string password)
        {
            if (string.IsNullOrEmpty(email))
            {
                ModelState.AddModelError("userName", ResourceReader.Current.GetString("$RequiredValidator"));
            }
            else
            {
                if (!ValidationHelper.Current.ValidateEmail(email))
                {
                    ModelState.AddModelError("userName", ResourceReader.Current.GetString("$EmailValidator"));
                }
            }

            if (string.IsNullOrEmpty(password))
            {
                ModelState.AddModelError("password", ResourceReader.Current.GetString("$RequiredValidator"));
            }

            if (ModelState.IsValid && !ValidateUser(email, password))
            {
                //ModelState.AddModelError("_FORM", "The userName or password provided is incorrect.");
                ModelState.AddModelError("userName", "The username or password provided is incorrect.");
            }

            if (ModelState.IsValid)
            {
                User user = AccountManager.Current.GetUser(email);
                if (!user.IsApproved)
                {
                    ModelState.AddModelError("userName", "User account is not activated.");
                }
                if (user.IsLockedOut)
                {
                    ModelState.AddModelError("userName", "User account is locked out.");
                }
            }

            return ModelState.IsValid;
        }

        #endregion

        #region Private methods

        private bool ValidateUser(string email, string password)
        {
            User user = AccountManager.Current.GetUser(email);
            if (user == null)
                return false;
            return HashHelper.Current.VerifyHash(password, user.Password, user.PasswordSalt);
        }

        #endregion
    }
}
